#include "./BSP/WDG/bsp_wdg.h"

/* -------------------------------------------- 全局变量定义 ------------------------------------------------- */

IWDG_HandleTypeDef g_iwdg_handle;   /* 独立看门狗句柄 */

/* ----------------------------------------- 独立看门狗(IWDG)函数 -------------------------------------------- */

/**
 * @brief       初始化独立看门狗
 * @param       prer: 预分频器值，可选范围：
 *              - IWDG_PRESCALER_4   (0x00): 4分频
 *              - IWDG_PRESCALER_8   (0x01): 8分频  
 *              - IWDG_PRESCALER_16  (0x02): 16分频
 *              - IWDG_PRESCALER_32  (0x03): 32分频
 *              - IWDG_PRESCALER_64  (0x04): 64分频
 *              - IWDG_PRESCALER_128 (0x05): 128分频
 *              - IWDG_PRESCALER_256 (0x06): 256分频
 * @param       rlr: 重装载寄存器值，范围0~0xFFF(0~4095)
 * @note        超时时间计算公式: Tout = ((4 * 2^prer) * rlr) / LSI_FREQ (ms)
 *              其中LSI_FREQ ≈ 40000Hz，实际频率有±40%误差
 *              最小超时时间约0.1ms，最大超时时间约26.2s
 *              IWDG一旦启动就无法停止，只能通过系统复位来停止
 * @retval      无
 */
void iwdg_init(uint8_t prer, uint16_t rlr)
{
    g_iwdg_handle.Instance = IWDG;
    g_iwdg_handle.Init.Prescaler = prer; /* 设置IWDG分频系数 */
    g_iwdg_handle.Init.Reload = rlr;     /* 重装载值 */
    HAL_IWDG_Init(&g_iwdg_handle);       /* 初始化IWDG并启动 */
}

/**
 * @brief       喂独立看门狗
 * @param       无
 * @note        必须在超时时间内定期调用此函数，否则系统将复位
 *              建议在主循环中定期调用，确保系统正常运行
 *              此函数会重装载IWDG计数器，重新开始倒计时
 * @retval      无
 */
void iwdg_feed(void)
{
    HAL_IWDG_Refresh(&g_iwdg_handle);  /* 重装载计数器 */
}

/* -------------------------------------------- 窗口看门狗(WWDG)函数 ----------------------------------------- */

//WWDG_HandleTypeDef g_wwdg_handle;  /* WWDG句柄 */

///**
// * @brief       初始化窗口看门狗
// * @param       tr: T[6:0]，计数器初始值，范围0x40~0x7F(64~127)
// *              计数器从此值开始递减，到达0x40时产生复位
// * @param       wr: W[6:0]，窗口值，范围0x40~0x7F(64~127)
// *              只有当计数器值小于此窗口值时才能刷新看门狗
// *              在窗口外刷新会立即产生系统复位
// * @param       fprer: 预分频器值，可选范围：
// *              - WWDG_PRESCALER_1: PCLK1/4096/1
// *              - WWDG_PRESCALER_2: PCLK1/4096/2
// *              - WWDG_PRESCALER_4: PCLK1/4096/4  
// *              - WWDG_PRESCALER_8: PCLK1/4096/8
// * @note        超时时间计算: Tout = (4096 * 2^fprer * (tr-0x40+1)) / PCLK1 (ms)
// *              其中PCLK1一般为36MHz或72MHz
// *              WWDG具有窗口期限制，只能在计数器值 < 窗口值时刷新
// *              本函数启用了提前唤醒中断，在计数器到达0x40时触发中断
// * @retval      无
// */
//void wwdg_init(uint8_t tr, uint8_t wr, uint32_t fprer)
//{
//    g_wwdg_handle.Instance = WWDG;
//    g_wwdg_handle.Init.Prescaler = fprer;         /* 设置分频系数 */
//    g_wwdg_handle.Init.Window = wr;               /* 设置窗口值 */
//    g_wwdg_handle.Init.Counter = tr;              /* 设置计数器值 */
//    g_wwdg_handle.Init.EWIMode = WWDG_EWI_ENABLE; /* 使能窗口看门狗提前唤醒中断 */
//    HAL_WWDG_Init(&g_wwdg_handle);                /* 初始化WWDG */
//}

///**
// * @brief       WWDG MSP初始化回调函数
// * @param       hwwdg: WWDG句柄指针
// * @note        此函数会被HAL_WWDG_Init()自动调用
// *              用于配置WWDG相关的时钟和中断
// *              中断优先级设置为抢占优先级2，子优先级3
// * @retval      无
// */
//void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
//{
//    __HAL_RCC_WWDG_CLK_ENABLE();            /* 使能窗口看门狗时钟 */

//    HAL_NVIC_SetPriority(WWDG_IRQn, 2, 3);  /* 抢占优先级2，子优先级为3 */
//    HAL_NVIC_EnableIRQ(WWDG_IRQn);          /* 使能窗口看门狗中断 */
//}

///**
// * @brief       窗口看门狗中断服务程序
// * @param       无
// * @note        当WWDG计数器到达0x40时触发此中断
// *              此函数会调用HAL库的通用中断处理函数
// *              然后调用用户定义的回调函数HAL_WWDG_EarlyWakeupCallback
// * @retval      无
// */
//void WWDG_IRQHandler(void)
//{
//    HAL_WWDG_IRQHandler(&g_wwdg_handle);  /* 调用WWDG共用中断处理函数 */
//}

///**
// * @brief       窗口看门狗提前唤醒中断回调函数
// * @param       hwwdg: WWDG句柄指针
// * @note        此函数会被HAL_WWDG_IRQHandler()自动调用
// *              在WWDG计数器到达0x40时触发，用于提前喂狗
// *              用户可以在此函数中添加其他需要在喂狗时执行的操作
// * @retval      无
// */
//void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
//{
//    HAL_WWDG_Refresh(&g_wwdg_handle); /* 更新窗口看门狗值 */
//}
